use libc::{__errno_location, close, open, pid_t, printf, strerror, write, O_WRONLY};
use std::ffi::{c_void, CString};
//must run with root
pub fn map_uid_gid(pid: pid_t) -> Result<(), String> {
    let c_string = CString::new(format!("/proc/{pid}/uid_map").as_str());
    let uid_file = if c_string.is_err() {
        return Err("error pid".to_string());
    } else {
        c_string.unwrap()
    };

    let c_string = CString::new(format!("/proc/{pid}/gid_map").as_str());
    let gid_file = if c_string.is_err() {
        return Err("error pid".to_string());
    } else {
        c_string.unwrap()
    };

    let c_string = CString::new(format!("/proc/{pid}/setgroups").as_str());
    let setgroup_file = if c_string.is_err() {
        return Err("error pid".to_string());
    } else {
        c_string.unwrap()
    };
    unsafe {
        let uid_file_d = open(uid_file.as_ptr(), O_WRONLY, 0666);
        let gid_file_d = open(gid_file.as_ptr(), O_WRONLY, 0666);
        let setgroup_file_d = open(setgroup_file.as_ptr(), O_WRONLY, 0666);
        if uid_file_d < 0 || gid_file_d < 0 || setgroup_file_d < 0 {
            close(uid_file_d);
            close(gid_file_d);
            close(setgroup_file_d);
            return Err("err open file".to_string());
        };
        let deny = c"deny";
        let len = deny.count_bytes();
        let i2 = write(setgroup_file_d, deny.as_ptr() as *const c_void, len + 1);

        let cstr = c"0 0 1";
        let len = cstr.count_bytes();

        let i = write(uid_file_d, cstr.as_ptr() as *const c_void, len + 1);
        let i1 = write(gid_file_d, cstr.as_ptr() as *const c_void, len + 1);
        if i < 0 || i1 < 0 || i2 < 0 {
            printf(c"%s\n".as_ptr(), strerror(*__errno_location()));
            close(uid_file_d);
            close(gid_file_d);
            close(setgroup_file_d);
            return Err("error write file".to_string());
        }
        close(uid_file_d);
        close(gid_file_d);
        close(setgroup_file_d);
        Ok(())
    }
}
